using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;

namespace YPFramework
{
    public class UIModule : MonoBehaviour
    {
        private Transform _topOri;
        private Transform _middleOri;
        private Transform _bottomOri;
        
        public Transform uiRoot;
        public Camera uiCamera;
        
        private static Dictionary<string, UIBase> _uiPanels = new();
        
        private void Start()
        {
            uiRoot = transform.Find("UIRoot");
            _topOri = uiRoot.Find("Top");
            _middleOri = uiRoot.Find("Middle");
            _bottomOri = uiRoot.Find("Bottom");
            uiCamera = uiRoot.Find("UICamera").GetComponent<Camera>();
            uiRoot.Find("Design").gameObject.SetActive(false);
        }

        /// <summary>
        /// 创建UI
        /// </summary>
        public async UniTask<T> CreateUI<T>() where T : UIBase
        {
            string key = typeof(T).Name;
            GameObject go = await Entry.Assets.LoadAssetAsync<GameObject>(typeof(T).Name);
            var basePanel = Instantiate(go, uiRoot).GetComponent<UIBase>();
            Entry.Assets.UnloadUnusedAssets();
            _uiPanels.Add(key, basePanel);
            ChangeLayer<T>(basePanel.layerType);
            basePanel.Create();
            return (T)basePanel;
        }

        /// <summary>
        /// 同步打开UI
        /// </summary>
        public void OpenUI<T>() where T : UIBase
        {
            OpenUIAsync<T>().ToCoroutine();
        }

        /// <summary>
        /// 异步打开UI
        /// </summary>
        public async UniTask<T> OpenUIAsync<T>() where T : UIBase
        {
            string key = typeof(T).Name;
            var basePanelController = _uiPanels.GetValueOrDefault(key);

            // 如果已有界面(之前缓存过的),则不执行任何操作
            if (basePanelController != null)
            {
                basePanelController.Open();
                return (T)basePanelController;
            }
            else
            {
                T basePanel = await CreateUI<T>();
                if(basePanel.layerType != UILayerType.Middle)
                    ChangeLayer<T>(basePanel.layerType);
                else
                    ChangeLayer<T>(UILayerType.Middle);
                basePanel.Open();
                return basePanel;
            }
        }

        
        /// <summary>
        /// 隐藏UI
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public void HideUI<T>() where T : UIBase
        {
            var panel = GetPanel<T>();
            if (panel != null)
                panel.Hide();
        }

        /// <summary>
        /// 获得UI实例
        /// </summary>
        public T GetPanel<T>() where T:UIBase
        {
            string key = typeof(T).Name;
            return _uiPanels.TryGetValue(key, out var panel) ? (T)panel : null;
        }

        /// <summary>
        /// 销毁UI
        /// </summary>
        public bool DisposeUI<T>() where T : UIBase
        {
            var panel = GetPanel<T>();
            if (panel != null)
            {
                panel.Dispose();
                _uiPanels.Remove(typeof(T).Name);
                return true;
            }
            else
            {
                Debug.LogWarning("此面板不存在, 无法销毁!");
                return false;
            }
        }
        
        /// <summary>
        /// 隐藏所有UI
        /// </summary>
        public void HideAllUI(UILayerType layerType = UILayerType.Middle)
        {
            foreach (var item in _uiPanels)
            {
                if(item.Value.layerType == layerType)
                    item.Value.Hide();
            }
        }

        /// <summary>
        /// 隐藏所有UI并打开指定UI
        /// </summary>
        public void HideAllUIAndOpen<T>(UILayerType layerType = UILayerType.Middle) where T : UIBase
        {
            HideAllUI(layerType);
            OpenUI<T>();
        }

        /// <summary>
        /// 改变UI层级
        /// </summary>
        public void ChangeLayer<T>(UILayerType layerType) where T : UIBase
        {
            var panel = GetPanel<T>();
            if (panel == null)
            {
                Debug.LogError(typeof(T).Name + "并未加载过，无法改变层级");
                return;
            }
            var parent = _middleOri;
            switch (layerType)
            {
                case UILayerType.Top:
                    parent = _topOri;
                    break;
                case UILayerType.Middle:
                    parent = _middleOri;
                    break;
                case UILayerType.Bottom:
                    parent = _bottomOri;
                    break;
            }
            panel.transform.SetParent(parent);
        }
    }
}
